/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2010 huliqing, huliqing.cn@gmail.com
 *
 * This file is part of QFaces.
 * QFaces is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * QFaces is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with QFaces.  If not, see <http://www.gnu.org/licenses/>.
 *
 * 这个文件是QFaces的一部分。
 * 您可以单独使用或分发这个文件，但请不要移除这个头部声明信息.
 * QFaces是一个自由软件，您可以自由分发、修改其中的源代码或者重新发布它，
 * 新的任何修改后的重新发布版必须同样在遵守LGPL3或更后续的版本协议下发布.
 * 关于LGPL协议的细则请参考COPYING、COPYING.LESSER文件，
 * 您可以在QFaces的相关目录中获得LGPL协议的副本，
 * 如果没有找到，请连接到 http://www.gnu.org/licenses/ 查看并获取副本。
 *
 * - Author: Huliqing
 * - Contact: huliqing.cn@gmail.com
 * - License: GNU Lesser General Public License (LGPL)
 * - Blog and source code availability: http://www.huliqing.name/
 */

Q.F.UIDynFrame = {
    init : function(ID_CLIENT, ID_FOR_VISIBLE_STATE, ID_FOR_POSITION_STATE, ID_FRAME, ID_HEADER, ID_CLOSE, 
    		renderBorder, renderCloseButton, drag, center, shade, shadeColor, shadeOpaque, onOpen, onClose) {
        var frame = new Q.F.UIDynFrame.Frame(ID_CLIENT, ID_FOR_VISIBLE_STATE, ID_FOR_POSITION_STATE, ID_FRAME, ID_HEADER, ID_CLOSE, 
        		renderBorder, renderCloseButton, drag, center, shade, shadeColor, shadeOpaque, onOpen, onClose);
        Q.F.put(ID_CLIENT, frame);
    }
}
Q.F.UIDynFrame.Frame = function(ID_CLIENT, ID_FOR_VISIBLE_STATE, ID_FOR_POSITION_STATE, ID_FRAME, ID_HEADER, ID_CLOSE, 
		renderBorder, renderCloseButton, drag, center, shade, shadeColor, shadeOpaque, onOpen, onClose) {
    this.ID_CLIENT = ID_CLIENT;
    this.visibleState = Q.get(ID_FOR_VISIBLE_STATE);
    this.positionState = Q.get(ID_FOR_POSITION_STATE);
    this.frame = Q.get(ID_FRAME);
    this.headerObj = Q.get(ID_HEADER); // headerObj -> Header Zone
    this.closeObj = Q.get(ID_CLOSE); // closeObj -> Close Zone
    this.renderBorder = (renderBorder == "true");
    this.renderCloseButton = (renderCloseButton == "true");
    this.drag = (drag == "true");
    this.center = (center == "true");
    this.shade = (shade == "true");
    this.shadeColor = shadeColor;
    this.shadeOpaque = parseFloat(shadeOpaque);
    this.onOpen = new Function(onOpen);
    this.onClose = new Function(onClose);
	
    this.width = 0;
    this.height = 0;
	
    // 遮罩层
    this.shadeObj = null;
	
    // ---- Interface
	
    this.display = function(visible) {
        if (visible == null)
            this.isVisible() ? this.close() : this.open();
        else
            visible == true ? this.open() : this.close();
    }
	this.isVisible = function() {
        return (this.visibleState.value == "1");
    }
    this.setToCenter = function() {
        var c = this.getCenter();
        Q.U.setPosition(this.frame, c.x, (c.y - 50));
        this.updatePosition(c.x, (c.y - 50));
    }
    this.moveToCenter = function(time) {
        var c = this.getCenter();
        this.moveTo(c.x, (c.y - 50), time);
    }
    this.moveTo = function(x, y, time, callback) {
        this.setVisible(true);
        if (this.shade)
            this.shadeObj.setVisible(true);
        Q.U.move(this.frame, x, y, time, callback);
        this.updatePosition(x, y);
    }
    this.displayShade = function(visible) {
        if (visible == null)
            this.shade = !this.isShade();
        else
            this.shade = (visible == true);
    }
    this.isShade = function() {
        return this.shade;
    }
    // ---- Init
    this.getCenter = function() {
    	this.getSize();
        var p = new Object();
        p.x = (Q.U.getViewportWidth() - this.width) / 2 + Q.U.getDocument().scrollLeft;
        p.y = (Q.U.getViewportHeight() - this.height) / 2 + Q.U.getDocument().scrollTop;
        return p;
    }
    this.getSize = function() {
    	var size = Q.U.getElementSize(this.getFrame());
    	if (size != null) {
    		this.width = size[0];
    		this.height = size[1];    		
    	}
    }
    this.getFrame = function() {
        return this.frame;
    }
    this.open = function() {
        if (this.onOpen.apply() == false)
            return;
        this.setVisible(true);
        if (this.center) this.setToCenter();
        if (this.shade)
            this.shadeObj.setVisible(true);
    }
    this.close = function() {
        if (this.onClose.apply() == false)
            return;
        this.setVisible(false);
        this.shadeObj.setVisible(false);
    }
    this.setVisible = function(visible) {
        visible = (visible != null) ? visible : true;
        if (visible) {
            this.frame.style.zIndex = Q.U.zIndex++;
            Q.U.open(this.frame);
            this.visibleState.value = "1";
        } else {
            Q.U.close(this.frame);
            this.visibleState.value = "0";
        }
    }
    // 更新组件中客户端中的位置
    this.updatePosition = function(x, y) {
    	this.positionState.value = (x + "," + y)
    	Q.debug("Update Client Position, p=" + this.positionState.value);
    } 
    this.toEnableDrag = function(id, parentId, frame) {
        var dragObj = Q.get(id);
        var moveObj = Q.get(parentId != null ? parentId : id);;
        dragObj.style.cursor = "move";
        moveObj.style.zIndex = Q.U.zIndex++;
        moveObj.style.position = "absolute";
        moveObj.offsetX = 0;
        moveObj.offsetY = 0;
        event_onmouseup = function(event) {
            document.onmousemove = "";
            Q.U.detachEvent(null, "onmouseup", event_onmouseup);
        }
        dragObj.onmousedown = function(event) {
            event = event ? event : window.event;
            moveObj.offsetX = event.clientX - moveObj.offsetLeft;
            moveObj.offsetY = event.clientY - moveObj.offsetTop;
            document.onmousemove = function(event) {
                event = event ? event : window.event;
                moveObj.style.left = event.clientX - moveObj.offsetX + "px";
                moveObj.style.top = event.clientY - moveObj.offsetY + "px";
                // 更新Frame位置信息
                frame.updatePosition(
                		(event.clientX - moveObj.offsetX), 
                		(event.clientY - moveObj.offsetY));
            }
            Q.U.attachEvent(null, "onmouseup", event_onmouseup);
        }
        moveObj.onmousedown = function(){moveObj.style.zIndex = Q.U.zIndex++;}
    }
    this.init = function() {
        // 必须一开始计算并记住宽高度（在组件被js所操作并改变之后，可能无法正确获得宽高度）
        this.getSize();
        Q.debug("frame width=" + this.width);
        Q.debug("frame height=" + this.height);
		
        // 这两个属性必须要求frame能够绝对定位，否则frame会被shade遮住，或者无法绝对居中
        if (this.shade || this.center) {
            this.getFrame().style.position = "absolute";
        }
        
        // 遮罩层
        this.shadeObj = new Q.F.UIDynFrame.Shade(this.getFrame());
        this.shadeObj.setColor(this.shadeColor);
        this.shadeObj.setOpaque(this.shadeOpaque);
		
        // 初始化 Frame 位置
        if (this.positionState != null && this.positionState.value != null) {
        	if (this.positionState.value != "-1,-1") { // Ignore if "-1,-1". 
        		var position = this.positionState.value.split(",");
        		if (position != null && position.length >= 2) {
        			var x = parseInt(position[0], 10);
        			var y = parseInt(position[1], 10);
        			x = (x != -1 ? x : null);
        			y = (y != -1 ? y : null);
        			Q.U.setPosition(this.getFrame(), x, y);
        			// 必须取消Center，否则在Open时仍会居中
        			this.center = false;
        		}        		
        	}
        }
        
        // 组件默认始终是不可见的(不管组件是否设置了visible=true)，
        // 所以这里必须初始化组件的可视化状态到正确的状态
        if (this.visibleState.value == "1") {
            this.open();
        }
        
        // 重新Handle Drag,以实时更新positionState
        if (this.drag && this.headerObj != null && this.frame != null) {
        	this.toEnableDrag(this.headerObj, this.frame, this);
        }
		
        // 如果没有渲染Frame边框，则不存在header,dragEabled,closeButton等元素，这里直接return.
        if (!this.renderBorder)
            return;
        var _self = this;
        if (this.renderCloseButton) {
            this.closeObj.onclick = function() {
                _self.close();
            }
        }
    }
    this.init();
}
Q.F.UIDynFrame.Shade = function(target) {
    this.mask = null;
    this.target = target; // frame.getFrame()
	
    this.init = function() {
        this.mask = document.createElement("div");
        this.mask.style.position = "absolute";
        this.mask.style.background = "black";
        this.setVisible(false);
        document.body.insertBefore(this.mask, document.body.firstChild);
    }
    this.display = function() {
        this.setVisible(!Q.U.isVisible(this.mask));
    }
    this.setVisible = function(visible) {
        if (visible) {
            this.resize();
            this.mask.style.zIndex = Q.U.zIndex++;
            this.target.style.zIndex = Q.U.zIndex++;
            Q.U.open(this.mask);
        } else {
            Q.U.close(this.mask);
        }
    }
    this.setOpaque = function(opaque) {
        Q.U.setOpaque(this.mask, opaque);
    }
    this.setColor = function(color) {
        this.mask.style.background = color;
    }
    this.resize = function() {
        // 保证高度能够覆盖全屏
        var h = Q.U.getViewportHeight();
        var r = Q.U.getElementSize(this.target);
        h = (h > document.body.scrollHeight ? h : document.body.scrollHeight);
        h = (h > r[1] ? h : r[1]); // 有可能target(frame的弹出窗口)的高度比当前整个viewport还高
        this.mask.style.width = document.body.scrollWidth + "px";
        this.mask.style.height = (h + 20) + "px";
    }
    this.init();
}
